#!/usr/bin/python3
# ******************************************************************************
# Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
# licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#     http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# ******************************************************************************/
import os

from lxml import etree

from conf import settings
from . import Api


class Github(Api):
    host = "https://api.github.com/repos"

    def __init__(self) -> None:
        super(Github, self).__init__()
        self.token = os.getenv("GITHUB_TOKEN", settings.token(name="github"))

    @property
    def _headers(self):
        headers = {
            "Accept": "application/vnd.github.v3+json",
        }
        if self.token:
            headers["Authorization"] = f"token {self.token}"
        return headers

    async def get_pull_commits(self, pull_number, page=100, curpage=1):
        """
        Get the commit contained in pr
        :param pull_number: pull number
        :param page: page number
        :param curpage: current page number
        :return: response
        """
        url = f"{self.host}/{self._owner}/{self._repo}/pulls/{pull_number}/commits"
        return await self._get(
            url, params=dict(per_page=page, page=curpage), headers=self._headers
        )

    async def get_pull_request(self, pull_number):
        """
        Get a pull request
        """
        url = f"{self.host}/{self._owner}/{self._repo}/pulls/{pull_number}"
        return await self._get(url, headers=self._headers)

    async def get_issue(self, issue_number):
        """
        Get issue information
        :param issue_number: issue num
        :return: response
        """
        url = f"{self.host}/{self._owner}/{self._repo}/issues/{issue_number}"
        return await self._get(url, headers=self._headers)

    async def get_issue_comments(self, issue_number):
        """
        Get issue comments
        :param issue_number: issue num
        :return: response
        """
        url = f"{self.host}/{self._owner}/{self._repo}/issues/{issue_number}/comments"

        return await self._get(url, headers=self._headers)

    async def create_issue(self, title, body):
        url = f"{self.host}/{self._owner}/{self._repo}/issues"
        params = {"title": title, "body": body}
        return await self._post(
            url=url, values=None, json=params, headers=self._headers
        )

    async def check_pull_merged(self, pull_number):
        """
        Check pr status
        :param pull_number: pull number
        :return: response
        """
        url = f"{self.host}/{self._owner}/{self._repo}/pulls/{pull_number}/merge"
        response = await self._get(url, headers=self._headers)
        if response.status_code == 204:
            return True
        return False

    @staticmethod
    def _pull(pulls):
        """
        Splicing pull
        :param pulls: pull url
        :return: full url
        """
        return ["https://github.com" + pr for pr in pulls]

    async def issue_relevance_pull(self, issue_number=None, issue_url=None):
        """
        Crawl issue URL information, get associated pr
        :param issue_number: issue num
        :param issue_url: issue url
        :return: pull list
        """
        if issue_url:
            response = await self._get(url=issue_url, text=True)
        else:
            response = await self._get(
                url=f"https://github.com/{self._owner}/{self._repo}/issues/{issue_number}",
                text=True,
            )
        if not response:
            return []

        html = etree.HTML(response)
        link = html.xpath(
            "//div[contains(@class,'discussion-sidebar-item') and contains(@class,'js-discussion-sidebar-item') "
            "and last() ]/form/div[contains(@class,'css-truncate')]"
        )
        if link:
            return self._pull(pulls=link[-1].xpath("./a/@href"))

        # Search for operation logs
        pulls = html.xpath(
            "//div[@class='TimelineItem']/div[@class='TimelineItem-body']//div[contains(@class,'flex-auto')]/a/@href"
        )
        return self._pull(pulls=pulls)
